package com.tanhua.admin.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tanhua.admin.enums.SexEnum;
import com.tanhua.admin.mapper.FreezingMapper;
import com.tanhua.admin.mapper.LoggingMapper;
import com.tanhua.admin.mapper.UserInfoMapper;
import com.tanhua.admin.mapper.UserMapper;
import com.tanhua.admin.pojo.*;
import com.tanhua.admin.vo.*;
import com.tanhua.dubbo.server.api.UserLikeApi;
import com.tanhua.dubbo.server.api.UsersApi;
import com.tanhua.dubbo.server.pojo.Video;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * @Author: JinboYang
 * @Description:
 * @Date: Created in 上午 9:07 2021/1/17
 * @ModifiedBy:
 */
@Service
@Slf4j
public class ManageService {

    @Value("${tanhua.sso.url}")
    private String ssoUrl;

    @Autowired
    private RestTemplate restTemplate;

    @Reference(version = "1.0.0")
    private UserLikeApi userLikeApi;

    @Reference(version = "1.0.0")
    private UsersApi usersApi;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private FreezingMapper freezingMapper;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private LoggingMapper loggingMapper;


    /**
     * 用户管理 - 用户数据翻页
     *
     * @param page
     * @param pagesize
     * @param id
     * @param nickname
     * @param city
     * @return
     */
    public PageResult userManager(String page, String pagesize, String id, String nickname, String city) {
        try {
            // 设置模糊查询条件
            LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            if (StringUtils.isNoneEmpty(id)) {
                lambdaQueryWrapper.like(UserInfo::getUserId, id);
            }
            if (StringUtils.isNoneEmpty(nickname)) {
                lambdaQueryWrapper.like(UserInfo::getNickName, nickname);
            }
            if (StringUtils.isNoneEmpty(city)) {
                lambdaQueryWrapper.like(UserInfo::getCity, city);
            }

            // 分页查询用户详细信息
            IPage<UserInfo> userInfoPage = userInfoMapper.selectPage(new Page<>(Long.valueOf(page), Long.valueOf(pagesize)), lambdaQueryWrapper);


            // 将查出的用户详细信息 封装到前端展示类中
            List<UsersVo> usersVoList = new ArrayList<>();
            for (UserInfo userInfo : userInfoPage.getRecords()) {

                Date lastActiveTime = loggingMapper.selectList(new LambdaQueryWrapper<Logging>().eq(Logging::getUserId, userInfo.getUserId()).orderByDesc(Logging::getLogout)).get(0).getLogout();

                UsersVo usersVo = UsersVo.builder()
                        .id(userInfo.getUserId())
                        .avatar(userInfo.getLogo())
                        .nickname(userInfo.getNickName())
                        .gender(userInfo.getSex().equals(SexEnum.MAN.getValue()) ? SexEnum.MAN.toString() : SexEnum.WOMAN.toString())
                        .age(userInfo.getAge())
                        .userStatus(userInfo.getState())
                        .city(userInfo.getCity())
                        .lastActiveTime(lastActiveTime.getTime())
                        .build();
                usersVoList.add(usersVo);
            }

            PageResult pageResult = PageResult.builder()
                    .page(Integer.valueOf(page))
                    .pagesize(Integer.valueOf(pagesize))
                    .pages(Math.toIntExact(userInfoPage.getPages()))
                    .counts(Math.toIntExact(userInfoPage.getTotal()))
                    .items(usersVoList)
                    .build();

            return pageResult;
        } catch (Exception e) {
            log.error("发送远程 RestTemplate 出错 ", e);
        }
        return null;
    }

    /**
     * 用户管理-用户基本资料
     *
     * @param userID 根据用户ID查询用户详细信息
     * @return
     */
    public UserBaseDataVo userBaseData(String userID) {
        UserBaseDataVo userBaseDataVo = UserBaseDataVo.builder()
                .id(Long.valueOf(userID))
                .build();

        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getUserId, userID);
        UserInfo userInfo = userInfoMapper.selectOne(queryWrapper);

        if (userInfo != null) {

            String sexStr = SexEnum.UNKNOWN.toString();
            if (userInfo.getSex().equals(SexEnum.MAN.getValue())) {
                sexStr = SexEnum.MAN.toString();
            } else {
                sexStr = SexEnum.WOMAN.toString();
            }

//            Date lastActiveTime = loggingMapper.selectList(new LambdaQueryWrapper<Logging>().eq(Logging::getUserId, userInfo.getUserId()).orderByDesc(Logging::getLogout)).get(0).getLogout();
//            String lastLoginLocation = loggingMapper.selectList(new LambdaQueryWrapper<Logging>().eq(Logging::getUserId, userInfo.getUserId()).orderByDesc(Logging::getLogout)).get(0).getLastLocation();
            Logging logging = mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userInfo.getUserId())).with(Sort.by(Sort.Order.desc("logout"))), Logging.class);


            userBaseDataVo.setNickname(userInfo.getNickName());
            userBaseDataVo.setSex(sexStr);
            userBaseDataVo.setAge(userInfo.getAge());
            userBaseDataVo.setIncome(Integer.valueOf(userInfo.getIncome()) * 10000);
            userBaseDataVo.setUserStatus(userInfo.getState());
            userBaseDataVo.setCreated(userInfo.getCreated().getTime());
            userBaseDataVo.setCity(userInfo.getCity());
            userBaseDataVo.setLogo(userInfo.getLogo());
            userBaseDataVo.setTags(userInfo.getTags());
            userBaseDataVo.setOccupation(userInfo.getIndustry());
            userBaseDataVo.setLastActiveTime(logging.getLogout().getTime());
            userBaseDataVo.setLastLoginLocation(logging.getLastLocation());
            userBaseDataVo.setMarriage(StringUtils.equals(userInfo.getMarriage() + "", "1") ? "已婚" : "未婚");
            userBaseDataVo.setPersonalSignature("白天不懂夜的黑");
            //粉丝数、喜欢数、配对数
            userBaseDataVo.setCountLiked(this.userLikeApi.queryLikeCount(Long.valueOf(userID)));
            userBaseDataVo.setCountBeLiked(this.userLikeApi.queryFanCount(Long.valueOf(userID)));
            userBaseDataVo.setCountMatching(this.userLikeApi.queryEachLikeCount(Long.valueOf(userID)));
        }

        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userID));

        if (user != null) {
            userBaseDataVo.setMobile(user.getMobile());
        }

        return userBaseDataVo;
    }

    /**
     * 用户管理-用户冻结操作
     *
     * @param freezing userId freezingTime freezingRange reasonsForFreezing frozenRemarks
     * @return
     */
    public Boolean freeze(Freezing freezing) {

        Freezing _freezing = freezingMapper.selectOne(new LambdaQueryWrapper<Freezing>().eq(Freezing::getUserId, freezing.getUserId()).isNull(Freezing::getReasonsForThawing));

        userInfoMapper.update(UserInfo.builder().userId(freezing.getUserId()).state("2").build(), new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, freezing.getUserId()));

        if (_freezing == null) {
            return freezingMapper.insert(freezing) > 0;
        } else {
            return freezingMapper.update(freezing, new LambdaQueryWrapper<Freezing>().eq(Freezing::getUserId, freezing.getUserId())) > 0;
        }

    }

    public Boolean unfreeze(Freezing freezing) {
        Freezing _freezing = freezingMapper.selectOne(new LambdaQueryWrapper<Freezing>().eq(Freezing::getUserId, freezing.getUserId()).isNull(Freezing::getReasonsForThawing));

        userInfoMapper.update(UserInfo.builder().userId(freezing.getUserId()).state("2").build(), new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, freezing.getUserId()));

        if (_freezing == null) {
            return null;
        } else {
            userInfoMapper.update(UserInfo.builder().userId(freezing.getUserId()).state("1").build(), new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, freezing.getUserId()));
            return freezingMapper.update(freezing, new LambdaQueryWrapper<Freezing>().eq(Freezing::getUserId, freezing.getUserId())) > 0;
        }

    }

    /**
     * 动态管理-动态分页
     *
     * @return
     */
    public PageResult auditingMovementsList(String pageNum, String pageSize, String uid, String state) {
        // 构造默认的返回参数
        PageResult pageResult = PageResult.builder()
                .pages(0)
                .page(Integer.valueOf(pageNum))
                .pagesize(Integer.valueOf(pageSize))
                .build();

        // 构造分页查询条件
        PageRequest pageRequest = PageRequest.of(Integer.valueOf(pageNum) - 1, Integer.valueOf(pageSize), Sort.by(Sort.Order.desc("created")));
        // 构造查询条件 包含 限制条件 和 分页条件

        Query query = Query.query(new Criteria()).with(pageRequest);
        if (StringUtils.isNotEmpty(uid)) {
            query = Query.query(Criteria.where("userId").is(Long.valueOf(uid))).with(pageRequest);
        }


        List<Publish> publishList = mongoTemplate.find(query, Publish.class);

        System.out.println(publishList);

        List<MovementsVo> movementsVoList = new ArrayList<>();
        for (Publish publish : publishList) {
            if (publish.getState() == null) {
                publish.setState("3"); //审核状态，1为待审核，2为自动审核通过，3为待人工审核，4为人工审核拒绝，5为人工审核通过，6为自动审核拒绝

                // 更新 审核状态 由 null 变为 1
                Update update = Update.update("state", "3");
                mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(publish.getId())), update, Publish.class);
            }
            MovementsVo movementsVo = MovementsVo.builder()
                    .id(publish.getId().toHexString())
                    .userId(publish.getUserId())
                    .createDate(publish.getCreated())
                    .text(publish.getText())
                    .state(publish.getState())
                    .medias((String[]) publish.getMedias().toArray(new String[0]))
                    .reportCount(0L)
                    .forwardingCount(0L)
                    .likeCount(0)
                    .commentCount(0)
                    .build();

            UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, publish.getUserId()));
            movementsVo.setNickname(userInfo.getNickName());
            movementsVo.setAvatar(userInfo.getLogo());

            // 设置点赞数
            String likeCountKey = "QUANZI_COMMENT_LIKE_" + movementsVo.getId();
            String likeCountValue = (String) redisTemplate.opsForValue().get(likeCountKey);
            if (likeCountValue != null) {
                movementsVo.setLikeCount(Integer.valueOf(likeCountValue));
            }

            // 设置评论数
            long count = mongoTemplate.count(
                    Query.query(
                            Criteria.where("publishId").is(publish.getId())
                                    .and("commentType").is(2)     // 评论类型, 1-点赞, 2-评论, 3-喜欢
                    ), Comment.class);
            movementsVo.setCommentCount(Math.toIntExact(count));

            movementsVoList.add(movementsVo);
        }

//        pageResult.setPages(RandomUtils.nextInt(50, 100));
        if (StringUtils.isNotEmpty(uid)) {
            pageResult.setCounts(publishList.size());
        } else {

            pageResult.setCounts(mongoTemplate.findAll(Publish.class).size());
        }
        pageResult.setItems(movementsVoList);

        return pageResult;

    }

    /**
     * 动态管理-动态通过审核
     *
     * @param publishIds 批量通过的 动态ID
     * @return 返回生效了多少条操作
     */
    public Long passAuditMovements(ArrayList<String> publishIds) {

        //审核状态，1为待审核，2为自动审核通过，3为待人工审核，4为人工审核拒绝，5为人工审核通过，6为自动审核拒绝

        // 更新 审核状态 由 null 变为 1
        Update update = Update.update("state", "5");
        Long count = 0L;
        for (String publishId : publishIds) {
            count = count + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(publishId)), update, Publish.class).getModifiedCount();
        }
        return count;

    }

    /**
     * 动态管理-撤销审核通过
     *
     * @param publishIds 批量通过的 动态ID
     * @return 返回生效了多少条操作
     */
    public Long revocationAuditMovements(ArrayList<String> publishIds) {
        //审核状态，1为待审核，2为自动审核通过，3为待人工审核，4为人工审核拒绝，5为人工审核通过，6为自动审核拒绝

        // 更新 审核状态 由 null 变为 1
        Update update = Update.update("state", "3");
        Long count = 0L;
        for (String publishId : publishIds) {
            count = count + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(publishId)), update, Publish.class).getModifiedCount();
        }
        return count;
    }

    /**
     * 动态管理-审核不通过
     *
     * @param publishIds 批量通过的 动态ID
     * @return 返回生效了多少条操作
     */
    public Long rejectAuditMovements(ArrayList<String> publishIds) {
        //审核状态，1为待审核，2为自动审核通过，3为待人工审核，4为人工审核拒绝，5为人工审核通过，6为自动审核拒绝

        // 更新 审核状态 由 null 变为 1
        Update update = Update.update("state", "4");
        Long count = 0L;
        for (String publishId : publishIds) {
            count = count + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(publishId)), update, Publish.class).getModifiedCount();
        }
        return count;
    }

    /**
     * 动态管理-视频记录翻页
     *
     * @return
     */
    public PageResult auditingVideoList(String pageNum, String pageSize, String uid, String state) {
        // 构造默认的返回参数
        PageResult pageResult = PageResult.builder()
                .pages(0)
                .page(Integer.valueOf(pageNum))
                .pagesize(Integer.valueOf(pageSize))
                .build();

        // 构造分页查询条件
        PageRequest pageRequest = PageRequest.of(Integer.valueOf(pageNum) - 1, Integer.valueOf(pageSize), Sort.by(Sort.Order.desc("created")));
        // 构造查询条件 包含 限制条件 和 分页条件

        Query query = Query.query(new Criteria()).with(pageRequest);
        if (StringUtils.isNotEmpty(uid)) {
            query = Query.query(Criteria.where("userId").is(Long.valueOf(uid))).with(pageRequest);
        }


        List<Video> videoList = mongoTemplate.find(query, Video.class);

        System.out.println(videoList);

        List<VideoVo> videoVoList = new ArrayList<>();
        for (Video video : videoList) {
            VideoVo videoVo = VideoVo.builder()
                    .id(video.getId())
                    .userId(video.getUserId())
                    .createDate(video.getCreated())
                    .videoUrl(video.getVideoUrl())
                    .picUrl(video.getPicUrl())
                    .reportCount(0L)
                    .forwardingCount(0L)
                    .likeCount(0L)
                    .commentCount(0L)
                    .build();

            UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, video.getUserId()));
            videoVo.setNickname(userInfo.getNickName());

            // 设置点赞数
            String likeCountKey = "QUANZI_COMMENT_LIKE_" + videoVo.getId();
            String likeCountValue = (String) redisTemplate.opsForValue().get(likeCountKey);
            if (likeCountValue != null) {
                videoVo.setLikeCount(Long.valueOf(likeCountValue));
            }

            // 设置评论数
            long count = mongoTemplate.count(
                    Query.query(
                            Criteria.where("publishId").is(videoVo.getId())
                                    .and("commentType").is(2)     // 评论类型, 1-点赞, 2-评论, 3-喜欢
                    ), Comment.class);
            videoVo.setCommentCount(Long.valueOf(String.valueOf(count)));

            videoVoList.add(videoVo);
        }
        if (StringUtils.isNotEmpty(uid)) {
            pageResult.setCounts(videoList.size());
        } else {

            pageResult.setCounts(mongoTemplate.findAll(Publish.class).size());
        }
        pageResult.setItems(videoVoList);

        return pageResult;


    }


    /**
     * 动态管理-查看登录日志
     *
     * @return
     */
    public PageResult queryLoggingListByMongoDB(String pageNum, String pageSize, String uid, String state) {
        PageResult pageResult = PageResult.builder()
                .page(Integer.valueOf(pageNum))
                .pagesize(Integer.valueOf(pageSize))
                .build();

        // 构造分页查询条件
        PageRequest pageRequest = PageRequest.of(Integer.valueOf(pageNum) - 1, Integer.valueOf(pageSize));

        // 构造查询条件 包含 限制条件 和 分页条件
        Query query = Query.query(new Criteria()).with(pageRequest);
        if (StringUtils.isNotEmpty(uid)) {
            query = Query.query(Criteria.where("userId").is(Long.valueOf(uid))).with(pageRequest);
        }

        List<Logging> loggingList = mongoTemplate.find(query, Logging.class);
        Long total = mongoTemplate.count(query, Logging.class);

        List<LoggingVo> loggingVoList = new ArrayList<>();
        Long count = 0L;
        for (Logging logging : loggingList) {
            LoggingVo loggingVo = LoggingVo.builder()
                    .id(count++)
                    .logTime(logging.getLogout().getTime())
                    .place(logging.getLastLocation())
                    .equipment(logging.getEquipment())
                    .build();
            loggingVoList.add(loggingVo);
        }
        pageResult.setCounts(Math.toIntExact(total));
        pageResult.setPages(Math.toIntExact(total / Integer.valueOf(pageSize) + 1));
        pageResult.setItems(loggingVoList);
        return pageResult;
    }

    /**
     * 动态管理-查看登录日志
     *
     * @return
     */
    public PageResult queryLoggingList(String pageNum, String pageSize, String uid, String state) {
        PageResult pageResult = PageResult.builder()
                .page(Integer.valueOf(pageNum))
                .pagesize(Integer.valueOf(pageSize))
                .build();

        IPage<Logging> loggingPage = loggingMapper.selectPage(new Page<>(Long.valueOf(pageNum), Long.valueOf(pageSize)), new LambdaQueryWrapper<Logging>().eq(Logging::getUserId, Long.valueOf(uid)));

        List<LoggingVo> loggingVoList = new ArrayList<>();
        Long count = 0L;
        for (Logging logging : loggingPage.getRecords()) {
            LoggingVo loggingVo = LoggingVo.builder()
                    .id(count++)
                    .logTime(logging.getLogout().getTime())
                    .place(logging.getLastLocation())
                    .equipment(logging.getEquipment())
                    .build();
            loggingVoList.add(loggingVo);
        }

        pageResult.setCounts(Math.toIntExact(loggingPage.getTotal()));
        pageResult.setPages(Math.toIntExact(loggingPage.getPages()));
        pageResult.setItems(loggingVoList);
        return pageResult;
    }

    /**
     * 动态管理 - 动态详情
     *
     * @param publishId 发布ID
     * @return
     */
    public MovementsVo queryMovementsInfo(String publishId) {


        Query query = Query.query(Criteria.where("_id").is(publishId));
        Publish publish = mongoTemplate.findOne(query, Publish.class);
        if (publish == null) {
            return null;
        }

        MovementsVo movementsVo = MovementsVo.builder()
                .id(publishId)
                .userId(publish.getUserId())
                .createDate(publish.getCreated())
                .text(publish.getText())
                .medias((String[]) publish.getMedias().toArray(new String[0]))
                .state(publish.getState())
                .reportCount(0L)
                .forwardingCount(0L)
                .likeCount(0)
                .commentCount(0)
                .build();

        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, publish.getUserId()));

        if (userInfo != null) {

            movementsVo.setNickname(userInfo.getNickName());
            movementsVo.setAvatar(userInfo.getLogo());
        }

        String likeCountKey = "QUANZI_COMMENT_LIKE_" + publish.getId();
        String likeCountValue = (String) redisTemplate.opsForValue().get(likeCountKey);
        if (StringUtils.isNotEmpty(likeCountValue)) {
            movementsVo.setLikeCount(Integer.valueOf(likeCountValue)); // 如果redis中查询出来的点赞数不为0,我们就设置该点赞数
        } else {
            movementsVo.setLikeCount(0);// 如果redis中未查到该键值对 我们就设为0
        }


        Query query2 = Query.query(
                Criteria.where("publishId").is(publishId)
                        .and("commentType").is(2)// 评论类型, 1-点赞, 2-评论, 3-喜欢
        );
        movementsVo.setCommentCount(Math.toIntExact(mongoTemplate.count(query2, Comment.class)));

        return movementsVo;
    }


    /**
     * 评论管理 - 评论列表翻页
     *
     * @return
     */
    public PageResult queryCommentsList(String pageNum, String pageSize, String sortProp, String sortOrder, String messageID) {
        // 封装默认的返回类
        PageResult pageResult = PageResult.builder().counts(0).pages(0).page(Integer.valueOf(pageNum)).pagesize(Integer.valueOf(pageSize)).build();

        Query query = Query.query(
                Criteria.where("publishId").is(new ObjectId(messageID))
                        .and("commentType").is(2)// 评论类型, 1-点赞, 2-评论, 3-喜欢
        );
        List<Comment> commentList = mongoTemplate.find(query, Comment.class);

        if (CollectionUtils.isEmpty(commentList)) {
            pageResult.setItems(Collections.emptyList());
            return pageResult;
        }

        List<CommentVo> commentVoList = new ArrayList<>();

        for (Comment comment : commentList) {
            CommentVo commentVo = CommentVo.builder()
                    .id(comment.getId().toHexString())
                    .userId(Math.toIntExact(comment.getUserId()))
                    .content(comment.getContent())
                    .createDate(comment.getCreated())
                    .build();

            UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, comment.getUserId()));
            commentVo.setNickname(userInfo.getNickName());

            commentVoList.add(commentVo);
        }
        pageResult.setItems(commentVoList);
        pageResult.setCounts(commentVoList.size());
        return pageResult;

    }
}
